package org.zergle.utils;

import java.util.LinkedList;
import java.util.Queue;

/**
 * 线程池
 * 
 * @author Johnson.Lee
 */
public class ThreadPool extends ThreadGroup {
	private boolean closed;
	private final int size;
	private Queue<Runnable> tasks;

	/**
	 * 默认线程池大小为10
	 */
	public ThreadPool(String id) {
		this(id, 10);
	}

	/**
	 * 初始化线程池时指定池的大小
	 * 
	 * @param size
	 *            线程池的大小
	 */
	public ThreadPool(String id, int size) {
		super(id);
		this.closed = true;
		this.size = size;
		this.setDaemon(true);
	}
	
	/**
	 * 初始化线程池
	 */
	public synchronized void init() {
		this.tasks = new LinkedList<Runnable>();
		for (int i = 0; i < this.size; i++) {
			Worker w = new Worker();
			w.start();
		}
		this.closed = false;
	}

	/**
	 * 执行任务
	 * 
	 * @param task
	 *            任务
	 * @throws IllegalStateException
	 *             当线程池关闭时，调用此方法会抛出此异常
	 */
	public synchronized void execute(Runnable task)
			throws IllegalStateException {
		if (this.isClosed())
			throw new IllegalStateException("ThreadPool is closed!");
		this.tasks.offer(task);
		this.notify();
	}

	/**
	 * 关闭线程池
	 */
	public synchronized void close() {
		if (!this.isClosed()) {
			readyForClose();
			this.tasks.clear();
			interrupt();
		}
	}

	/**
	 * 测试线程池是否关闭
	 * 
	 * @return 如果线程池已关闭则返回true，否则返回false
	 */
	public synchronized boolean isClosed() {
		return closed;
	}

	/**
	 * 从任务队列中获取任务
	 * 
	 * @param w
	 *            工作线程
	 * @return 返回任务
	 * @throws InterruptedException
	 */
	private synchronized Runnable getTask(Worker w) throws InterruptedException {
		while (this.tasks.isEmpty()) {
			if (this.isClosed())
				return null;
			this.wait();
		}
		return this.tasks.poll();
	}

	/**
	 * 准备关闭线程池
	 */
	private void readyForClose() {
		synchronized (this) {
			closed = true;
			notifyAll();
		}
		Thread[] threads = new Thread[activeCount()];
		int count = enumerate(threads);
		for (int i = 0; i < count; i++) {
			try {
				threads[i].join();
			} catch (InterruptedException e) {
				continue;
			}
		}
	}

	/**
	 * 工作线程
	 * 
	 * @author Johnson.Lee
	 * 
	 */
	private class Worker extends Thread {
		public void run() {
			Runnable task;
			while (!isInterrupted()) {
				try {
					task = getTask(this);
					if (task == null)
						continue;
					task.run();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}

	}
}
